<?php
/**
 * @file 3gplex/includes/contact.inc
 * 
 * Contact core module configuration API.
 * 
 */
require_once('./'. drupal_get_path('module', 'drupalplex') .'/includes/module.inc');

define("PCTCT_NO_NAME", "Can't create contact category without name");
define("PCTCT_NO_RECIPIENT", "Can't create contact category %category:
	It has no recipients");
define("PCTCT_INVALID_RECIPIENT", "Can't create contact category %category:
	%recipient is not a valid email address");

class plex_contact_exception extends plex_exception
{
	function __construct($message, $category)
	{
		$this->message = $message;
		$this->arguments = array('%category'=>$category);
	}
}

/**
 * Contact core module wrapper.
 * 
 * This module adds to a drupal site a contact form with various usual settings
 * as 'who contacted' 'for what'... These settings are embedded in what is called
 * a 'category' and are available through an XML file.
 */
class plex_contact extends plex_module
{
	const description = "Configures and loads API for Drupal core contact module: Contact form for your Drupal site";
	function get_description() { return self::description; }
	/** Default weight of categories is 0. */
	const default_weight = 0;
	/** There's no default reply to people sending messages. */
	const default_reply = '';

	/**
	 * 
	 */
	protected function build_settings_xml($xml)
	{
		$settings = array();
		if (isset($xml->infos)) $settings['infos'] = (string)$xml->infos;
		if (isset($xml->treshold)) $settings['treshold'] = (int)(string)$xml->treshold;
		if (isset($xml->default_status)) $settings['default_status'] = (int)(string)$xml->default_status;
		
		$settings['categories'] = array();
		foreach ($xml->category as $category) {
			$new = array();
			if (!isset($category->name) || strlen((string)$category->name) < 1)
				throw new plex_exception(PCTCT_NO_NAME);
			$new['recipients'] = array();
			foreach ($category->recipients->recipient as $recipient) {
				$new['recipients'][] = (string)$recipient;
			}
			if (isset($category->weight)) $new['weight'] = (int)(string)$category->weight;
			if (isset($category->reply)) $new['reply'] = (string)$category->reply;
			if (isset($category->selected)) $new['selected'] = (boolean)(int)$category->selected;
			$settings['categories'][(string)$category->name] = $new;
		}
		return $settings;
	}

	protected function validate_settings(array &$settings)
	{
		if (!isset($settings['infos'])) $settings['infos'] = '';
		if (!isset($settings['treshold'])) $settings['treshold'] = 3;
		if (!isset($settings['default_status'])) $settings['default_status'] = 0;
		$settings['categories'] = (array)$settings['categories'];
		reset($settings['categories']);
		while (list($name, ) = each($settings['categories'])) {
			$this->validate_category_settings($name, $settings['categories']);
		}
	}

	protected function validate_category_settings($name, array &$categories)
	{
		if (strlen($name) < 1 || !isset($categories[$name])) {
			throw new plex_exception(PCTCT_NO_NAME);
		}
		if (!isset($categories[$name]['recipients']) || !is_array($categories[$name]['recipients'])) {
			throw new plex_contact_exception(PCTCT_NO_RECIPIENT, $name);
		}
		foreach ($categories[$name]['recipients'] as $key => $recipient) {
			$recipient = trim((string)$recipient);
			$categories[$name]['recipients'][$key] = $recipient;
			if (!valid_email_address($recipient)) {
				throw new plex_exception(PCTCT_INVALID_RECIPIENT,
				array('%category'=>$categories[$name]['name'], '%recipient'=>$recipient));
			}
		}
		if (!isset($categories[$name]['weight'])) $categories[$name]['weight'] = self::default_weight;
		if (!isset($categories[$name]['reply'])) $categories[$name]['reply'] = self::default_reply;
		if (!isset($categories[$name]['selected'])) $categories[$name]['selected'] = false;
	}

	/**
	 * 
	 */
	protected function apply_settings(array &$settings)
	{
		variable_set('contact_form_information', $settings['infos']);
		variable_set('contact_hourly_treshold', $settings['treshold']);
		variable_set('contact_default_status', $settings['default_status']);
		reset($settings['categories']);
		while (list($name, ) = each($settings['categories'])) {
			$this->apply_category_settings($name, $settings['categories']);
		}
	}

	protected function apply_category_settings($name, array &$categories)
	{
		if ($categories[$name]['selected']) {
			db_query('update {contact} SET selected = 0');
		}
		$recipients = implode(',', $categories[$name]['recipients']);
		if ($this->category_exists($name)) {
			db_query("update {contact} set
				recipients = '%s',
				reply = '%s',
				weight = %d,
				selected = %d
			where category = '%s'",
				$recipients,
				$categories[$name]['reply'],
				$categories[$name]['weight'],
				$categories[$name]['selected'],
				$name
			);
	    		plex::notice("Contact form category %category has been updated.", array('%category' => $name));
		} else {
			db_query("insert into {contact} (
				category, recipients, reply, weight, selected) VALUES ('%s', '%s', '%s', %d, %d)",
				$name,
				$recipients,
				$categories[$name]['reply'],
				$categories[$name]['weight'],
				$categories[$name]['selected']
			);
	    		plex::notice("Contact form category %category has been added.", array('%category' => $name));
		}
	}

	/**
	 * 
	 */
	protected function revert_settings($settings)
	{
		variable_del('contact_form_information');
		variable_del('contact_hourly_treshold');
		variable_del('contact_default_status');
		reset($settings['categories']);
		while (list($name, ) = each($settings['categories'])) {
			$this->rem_category($name);
		}
	}

	/**
	 * Returns true if the contact category of the given name already exists, false otherwise.
	 */
	function category_exists($name)
	{
		$res = db_query("select 1 from {contact} where category='%s'", $name);
		if ($res === false || db_num_rows($res) < 1) return false;
		return true;
	}
	
	/**
	 * Returns the id of the contact category of the given name if it exists, -1 otherwise.
	 */
	function category_name2id($name)
	{
		$res = db_query("select cid from {contact} where category='%s'", $name);
		if ($res === false || db_num_rows($res) < 1) return -1;
		return db_result($res);
	}
	
	/**
	 * Creates a contact category according to the settings provided as argument.
	 */
	function add_category($name, $recipients, $weight = 0, $reply = '', $selected = false)
	{
		$c = array(
			'recipients' => $recipients,
			'weight' => $weight,
			'reply' => $reply,
			'selected' => $selected,
		);
		try {
			$this->validate_category_settings($name, $c);
			$this->apply_category_settings($name, $c);
		
		} catch (plex_exception $err) {
			$err->display();
			return false;
		}
		return true;
	}

	/**
	 * Delete the contact category of the given name.
	 */
	function rem_category($name)
	{
		db_query("delete from {contact} where category='%s'", $name);
	    	plex::notice("Contact form category %category has been deleted.", array('%category' => $name));
	}
}
